/**
 * JAVACC DEMO 1.0
 * @copy right apache company All rights reserved. 
 * @Package com.apache.rpc.server.impl  
 */
package com.apache.rpc.server.impl;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.LinkedHashMap;
import java.util.Map;

import com.apache.api.api.SystemService;
import com.apache.api.api.SystemService.ParamType;
import com.apache.cache.util.Validator;
import com.apache.database.constant.SpringContextLoader;
import com.apache.rpc.util.XMLMapParse;

/**
 * description:  
 * @author Hou Dayu 创建时间：2015-1-7  
 * @Copyright(c)2014:
 */
public class ClientSocketLisener {

	private static ClientSocketLisener instance = new ClientSocketLisener();
	/** 
	* 连接对象保持，只保持需要系统保持的连接 
	*/
	public static Map<String, Socket> socketMap = new LinkedHashMap<String, Socket>();

	private ClientSocketLisener() {

	}

	public synchronized static ClientSocketLisener getinstance() {
		if (null == instance) {
			instance = new ClientSocketLisener();
		}
		return (instance);
	}

	public void setClientSocket(Socket socket) {
		String key = socket.getRemoteSocketAddress().toString() + "_queryQuotationList";//.getInetAddress().getHostAddress();//
		if (!socketMap.containsKey(key)) {
			socketMap.put(key, socket);
		}
	}

	public void setClientSocket(Socket socket, String key) {
		if (!socketMap.containsKey(key)) {
			socketMap.put(key, socket);
		}
	}

	public void removeSocket(String key) {
		socketMap.remove(key);
	}

	//	public synchronized Socket getClicentSocket(Socket socket) {
	//		String key = socket.getRemoteSocketAddress().toString();
	//		if (socketMap.containsKey(key)) {
	//			System.out.println("get key =" + key);
	//			return socketMap.get(key);
	//		}
	//		return socket;
	//	}

	public String doService(String xmls, String paramType, boolean isEncrypt) {
		String result = "";
		SystemService service = null;
		if (isEncrypt) {//加密方式
			service = (SystemService) SpringContextLoader.getBean("protocol_encry_systemService");
		} else {
			if (!xmls.startsWith("<?xml"))
				xmls = XMLMapParse.instance().jsonToXMl(xmls);
			service = (SystemService) SpringContextLoader.getBean("protocol_systemService");
		}
		result = service.doService(xmls, getParamType(paramType));
		return result;
	}

	private ParamType getParamType(String type) {
		if ("json".equalsIgnoreCase(type)) {
			return ParamType.JSON;
		} else {
			return ParamType.XML;
		}
	}

	/**
	 * description:  向长连接的客户端推消息
	 * @param str   消息内容(json)
	 * @author Hou Dayu  
	 * @update 2015-1-8
	 */
	public void sendToClient(String str) {
		if (Validator.isNull(str))
			return;
		sendMessageForClients(str, "");
	}

	/**
	 * description:  向长连接的客户端推消息
	 * @param str   消息内容(json)
	 * @author Hou Dayu  
	 * @update 2015-1-8
	 */
	public void sendToClient(String str, String methodKey) {
		if (Validator.isNull(str))
			return;
		sendMessageForClients(str, methodKey);
	}

	private void sendMessageForClients(String str, String methodKey) {
		methodKey = Validator.getDefaultStr(methodKey, "queryQuotationList");
		for (String key : socketMap.keySet()) {
			if (!key.endsWith(methodKey)) {
				continue;
			}
			Socket socket = socketMap.get(key);
			try {
				if (socket != null && socket.isConnected() && !socket.isClosed()) {
					byte[] data_byte_arr = str.getBytes("UTF-8");
					int data_len = data_byte_arr.length;
					byte[] data_byte_len = Int2BytesLH(data_len);
					OutputStream os = socket.getOutputStream();
					//发送实际数据长度
					os.write(data_byte_len, 0, data_byte_len.length);
					//发送实际数据内容
					os.write(data_byte_arr, 0, data_byte_arr.length);
					os.flush();
				}
			} catch (Exception e) {
				try {
					socket.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				ClientSocketLisener.getinstance().removeSocket(key);
				e.printStackTrace();
			}
		}
	}

	/**
	 * description:  将int转成字节数组
	 * @param n
	 * @return   
	 */
	private byte[] Int2BytesLH(int n) {
		byte[] b = new byte[4];
		b[0] = (byte) (n & 0xff);
		b[1] = (byte) (n >> 8 & 0xff);
		b[2] = (byte) (n >> 16 & 0xff);
		b[3] = (byte) (n >> 24 & 0xff);
		return b;
	}
	/** 
	* 判断是否断开连接，断开返回true,没有返回false 
	* @param socket 
	* @return 
	*/
	//	private Boolean isServerClose(Socket socket) {
	//		try {
	//			// 发送一个心跳包  
	//			socket.sendUrgentData(0xFF);
	//			return false;
	//		} catch (Exception se) {
	//			try {
	//				socket.close();
	//			} catch (IOException e) {
	//			}
	//			return true;
	//		}
	//	}
}
